__all__ = ['PointPlotter', 'ArrayPlotter', 'TextPlotter', 'ImagePlotter', 'GifPlotter', 'AudioPlotter']

import abc
from collections import Counter

import jieba
import numpy as np
from sklearn import decomposition

import librosa.display
import matplotlib.pyplot as plt
from wordcloud import WordCloud

from ImageShop import ImageShop as IS

plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号

class Plotter(abc.ABC):
    """
    Abstract Plotter Base Class
    """

    def __init__(self, data):
        self.data = data

    @abc.abstractmethod
    def plot(self, *args, **kwargs):
        pass


class PointPlotter(Plotter):
    """
    绘制二维点
    """

    def __init__(self, data):
        super(PointPlotter, self).__init__(data)

    def plot(self, *args, **kwargs):
        x, y = zip(*self.data)
        plt.scatter(x, y)
        plt.show()


class ArrayPlotter(Plotter):
    """
    绘制n维数组，二维绘制为平面图，三维绘制为3D图，更高维进行PCA处理后绘制二维坐标图
    """

    def __init__(self, data):
        super(ArrayPlotter, self).__init__(data)

    def plot(self, *args, **kwargs):
        d = len(self.data)
        print(d)
        if d > 1:
            da = self.data
            fig = plt.figure()
            if d == 2:
                plt.scatter(da[0], da[1])
            elif d == 3:
                ax = fig.gca(projection='3d')
                ax.scatter(da[0], da[1], da[2])
            else:
                n = np.asarray(da)
                pca = decomposition.PCA(n_components=2)
                pca.fit(n)
                print(pca.explained_variance_ratio_)
                n_new = pca.transform(n)
                plt.scatter(n_new[:, 0], n_new[:, 1])
            plt.show()
        else:
            raise ValueError("数据维数必须大于一维！")


class TextPlotter(Plotter):
    """
    绘制词云
    """

    def __init__(self, data):
        super(TextPlotter, self).__init__(data)

    def plot(self, *args, **kwargs):
        word_list_pre = jieba.lcut(self.data)
        word_stat_pre = Counter(word_list_pre)
        stopwords = set()
        with open("stopwords_list.txt", "r", encoding='utf8') as s:
            for i in s.readlines():
                stopwords.add(i.replace("\n", ""))
        word_stat = word_stat_pre.copy()
        for key in word_stat_pre:
            if key in stopwords:
                word_stat.pop(key)
        wordcloud = WordCloud(background_color="white", font_path="C:/Windows/Fonts/simhei.ttf").fit_words(word_stat)
        plt.imshow(wordcloud)
        plt.axis("off")
        plt.show()


class ImagePlotter(Plotter):
    """
    根据路径和图片类型，展示图片
    """

    def __init__(self, path, img_type, row, col, size, max_num=0):
        super(ImagePlotter, self).__init__(path)
        self.params = dict(row=row, col=col, size=size, max_num=max_num, img_type=img_type)

    def plot(self, *args, **kwargs):
        IP = IS(self.data, img_type=self.params.pop("img_type"))
        IP.load_images()
        IP.display(**self.params)


class GifPlotter(Plotter):
    """
    根据路径、图片类型和尺寸，生成指定时间间隔的GIF图片
    """

    def __init__(self, path, img_type, width, height):
        super(GifPlotter, self).__init__(path)
        self.param = (img_type, width, height)

    def plot(self, filename, duration):
        IP = IS(self.data, img_type=self.param[0])
        IP.load_images()
        IP.batch_ps(("Resize", self.param[1:]))
        image_list = IP.get_results()
        save_name = f"{filename}.gif"
        image_list[0].save(save_name, save_all=True, append_images=image_list, duration=duration)
        print(f"GIF result was saved in {save_name}")
        return save_name


class AudioPlotter(Plotter):
    """
    绘制波形文件的声音频率图
    """

    def __init__(self, path):
        super(AudioPlotter, self).__init__(path)

    def plot(self, *args, **kwargs):
        audio_path = self.data
        music, sr = librosa.load(audio_path)

        # 宽高比为14:5的图
        plt.figure(figsize=(50, 5))
        librosa.display.waveplot(music, sr=sr)

        # 显示图
        plt.show()
